package com.example.showcase.web;

import com.example.showcase.common.ChannelStatInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.stat.ChannelStat;
import org.tio.server.ServerGroupContext;
import org.tio.utils.lock.SetWithLock;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@RestController
public class ServerController {

    static Logger LOG = LoggerFactory.getLogger(ServerGroupContext.class);
    @Autowired
    ServerGroupContext serverGroupContext;

    @RequestMapping("/")
    public Object home() {

        SetWithLock<ChannelContext> setWithLock = Aio.getAllChannelContexts(serverGroupContext);
        Set<ChannelContext> set = null;
        ReentrantReadWriteLock.ReadLock readLock = setWithLock.getLock().readLock();
        List<ChannelStatInfo> list = null;
        try {
            readLock.lock();
            set = setWithLock.getObj();
            list = new ArrayList<>();

            for (ChannelContext channelContext : set) {

                ChannelStatInfo info = new ChannelStatInfo();
                ChannelStat stat = channelContext.getStat();

                String ip = channelContext.getClientNode().getIp(); // 客户端IP
                int port = channelContext.getClientNode().getPort(); // local_port
                int reconnCount = channelContext.getReconnCount(); // 重连次数
                int decodeFailCount = stat.getDecodeFailCount(); // 解码异常次数
                String userId = channelContext.getUserid(); // 用户ID
                String token = channelContext.getToken(); // 用户token
                long timeStart = stat.getTimeCreated(); // 统计开始时间
                // 统计时长
                AtomicLong receivedBytes = stat.getReceivedBytes(); // 已接收字节
                AtomicLong receivedPackets = stat.getReceivedPackets(); // 已接收业务包
                AtomicLong receivedTcps = stat.getReceivedTcps(); // 已接收TCP包

                double bytesPerTcpReceive = stat.getBytesPerTcpReceive(); // 平均每次TCP包接收的字节数
                double packetsPerTcpReceive = stat.getPacketsPerTcpReceive(); // 平均每次TCP包接收的业务包

                AtomicLong handledBytes = stat.getHandledBytes(); // 已处理字节
                AtomicLong handledPackets = stat.getHandledPackets(); // 已处理业务包

                AtomicLong sentBytes = stat.getSentBytes(); // 已发送字节数
                AtomicLong sentPackets = stat.getSentPackets(); // 已发送业务包

                long timeLatestReceivedMsg = stat.getLatestTimeOfReceivedByte();
                long timeLatestSentMsg = stat.getLatestTimeOfSentPacket();
                long latestCommunicateTime = Math.max(timeLatestReceivedMsg, timeLatestSentMsg); // 最近一次通信时间


                info.setClientIp(ip);
                info.setPort(port);
                info.setReConnCount(reconnCount);
                info.setDecodeFailCount(decodeFailCount);
                info.setUserId(userId);
                info.setToken(token);
                info.setGmtCreate(new Date(timeStart));
                info.setReceivedBytes(receivedBytes);
                info.setReceivedPackets(receivedPackets);
                info.setReceivedTcps(receivedTcps);
                info.setBytesPerTcpReceive(bytesPerTcpReceive);
                info.setPacketsPerTcpReceive(packetsPerTcpReceive);
                info.setHandledBytes(handledBytes);
                info.setHandledPackets(handledPackets);
                info.setSentBytes(sentBytes);
                info.setSentPackets(sentPackets);
                info.setGmtLatestCommunicate(new Date(latestCommunicateTime));
                list.add(info);

                LOG.info("Current Client Info : [{}].", info);
            }
        } catch (Throwable e) {
            LOG.error("", e);
        } finally {
            readLock.unlock();
        }

        serverGroupContext.setHeartbeatTimeout(60 * 1000);
        return list;
    }

}
